﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", sizeof(arr));//7
//	printf("%zd\n", sizeof(arr + 0));//arr是首元素的地址，是地址就是 4/8
//	printf("%zd\n", sizeof(*arr));//arr 是首元素的地址，*arr首元素的内容 1
//	printf("%zd\n", sizeof(arr[1]));//第二个元素 1
//	printf("%zd\n", sizeof(&arr));// &arr取出的是整个数组的地址，是地址就是4/8
//	printf("%zd\n", sizeof(&arr + 1));// &arr是整个数组的地址，加一就是跳过这个数组的地址，是地址就是4/8
//	printf("%zd\n", sizeof(&arr[0] + 1));//首元素的地址加一，就是第二个元素的地址，是地址就是4/8
//
//
//	return 0;
//}


//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", strlen(arr));//6
//	printf("%d\n", strlen(arr + 0));//arr是首元素的地址arr+0  依然是首元素的地址 6
//	//printf("%d\n", strlen(*arr));//arr是首元素的地址 *arr是首元素  'a'  的Ascll码是97所以和前面的题一样
//	// 这个的程序会崩溃
//	//printf("%d\n", strlen(arr[1]));//arr[1]是第二个元素，‘b’的Ascll码值是 98 程序也会崩溃
//	printf("%d\n", strlen(&arr));//&arr取出了整个数组的地址，6
//	printf("%d\n", strlen(&arr + 1));// 跳过整个数组的地址， 随机值
//	printf("%d\n", strlen(&arr[0] + 1));//从第二个元素的地址找， 5
//
//	return 0;
//}
//int main()
//{
//	char* p = "abcdef";
//	printf("%zd\n", sizeof(p));//p是指针变量，计算指针变量的大小 4/8字节
//	printf("%zd\n", sizeof(p + 1));// p是指针变量，p+1是第二个元素的地址，4/8字节
//	printf("%zd\n", sizeof(*p));// p是指针变量， *p 是首元素的大小，1
//	printf("%zd\n", sizeof(p[0]));// p[0]首元素的大小 1
//	printf("%zd\n", sizeof(&p));// &p是p的地址，是地址就是4/8
//	printf("%zd\n", sizeof(&p + 1));//跳过 p变量的地址，指向p后面的地址  4/8
//	printf("%zd\n", sizeof(&p[0] + 1));// &p[0]是首元素的地址，加1是第二个元素的地址， 4/8
//
//
//	return 0;
////}
//#include<string.h>
//int main()
//{
//	char* p = "abcdef";
//	printf("%zd\n", strlen(p));//6
//	printf("%zd\n", strlen(p + 1));//从第二元素的地址开始，5
//	//printf("%zd\n", strlen(*p));//p是指针变量，首元素的内容 ，‘a’--97  程序崩溃 
//	//printf("%zd\n", strlen(p[0]));//和上面的一样 都是首元素 a
//	printf("%zd\n", strlen(&p));//&p和p是两个地址， 所以是随机值
//	printf("%zd\n", strlen(&p + 1));//&p+1 就是跳过p的地址，随机值
//	printf("%zd\n", strlen(&p[0] + 1));//首元素地址加一，就是第二个元素的地址 5
//
//
//	return 0;
//}
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//整个数组的大小，12* 4就是48
//	printf("%zd\n", sizeof(a[0][0]));//arr[0] 的首个元素 4
//	printf("%zd\n", sizeof(a[0]));// arr[0] 里面有四个字节 ，就是16
//	printf("%zd\n", sizeof(a[0] + 1));//arr[0]是数组名地址没有单独放在sizeof里面，
//	//那就代表的是arr[0]首元素的地址 ， 加一就是arr[0]的第二个地址 4/8字节
//	printf("%zd\n", sizeof(*(a[0] + 1)));//arr[0]的第二个元素的内容  4
//	printf("%zd\n", sizeof(a + 1));//这里的a没有单独放在sizeof里，
//	//a表示首元素的地址 arr[0]+1 就是arr[1]的地址 4/8
//	printf("%zd\n", sizeof(*(a + 1)));//a是首元素地址  *（a+1）--> a[1]  16
//	printf("%zd\n", sizeof(&a[0] + 1));//跳过arr[0]的地址 计算arr[1]的地址 是地址就是4/8
//	printf("%zd\n", sizeof(*(&a[0] + 1)));// *  &可以抵消，那么就是 arr[1]的元素 16
//	printf("%zd\n", sizeof(*a));//这里a没有单独放在sizeof里 那摩就是首元素的地址 arr[0],
//	//*arr[0]就是这个数组的元素大小  16
//	printf("%zd\n", sizeof(a[3]));//这里会不会越界访问呢？ 答案是：
//	//不会，因为sizeof 内部表达式不会真实的计算 arr[3]就是第4行的数组大小 16 
//
//
//	return 0;
//}

//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%d\n", sizeof(a));
//	printf("%d\n", sizeof(a[0][0]));
//	printf("%d\n", sizeof(a[0]));
//	printf("%d\n", sizeof(a[0] + 1));
//	printf("%d\n", sizeof(*(a[0] + 1)));
//	printf("%d\n", sizeof(a + 1));
//	printf("%d\n", sizeof(*(a + 1)));
//	printf("%d\n", sizeof(&a[0] + 1));
//	printf("%d\n", sizeof(*(&a[0] + 1)));
//	printf("%d\n", sizeof(*a));
//	printf("%d\n", sizeof(a[3]));
//
//
//	return 0;
//}

////在X86环境下 //假设结构体的⼤⼩是20个字节 //程序输出的结果是啥？ 
//struct Test
//{
//		int Num;
//		char* pcName;
//		short sDate;
//		char cha[2];
//		short sBa[4];
//}*p = (struct Test*)0x100000;
//
//
//int main()
//{
//	printf("%p\n", p + 0x1);//这里的p是结构体 20个字节，转换成十六进制就是14 0x100014
//	printf("%p\n", (unsigned long)p + 0x1);//整形+1 就是在基础上加一 0x100001
//	printf("%p\n", (unsigned int*)p + 0x1);//这里指针类型是int 所以 0x100004
//	return 0;
//}
//
// 
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
//int main()
//{
//	printf("%p\n", p + 0x1);
//	printf("%p\n", (unsigned long)p + 0x1);
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}
//#include <stdio.h>
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//因为数组里面用的是小括号，表达式是逗号表达式，
//	所以这个里面是{1，3，5} 打印p[0]就是打印首元素 ，那么1就是首元素
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);
//	return 0;
//}
////#include <stdio.h>
//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//这里是两行五列的
//	//1, 2, 3, 4, 5										大概就是这样	
//	//6, 7, 8, 9, 10
//	int* ptr1 = (int*)(&aa + 1);//&aa是整个数组的地址 +1跳过整个数组的地址这时候 ptr1 指向 10的后面
//	int* ptr2 = (int*)(*(aa + 1));//*（aa+1）--> aa[1] 就是第二行的数组内容 ptr 2指向 6
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//这时 ptr1 -1想后移动一位 10 ， ptr2 6 -1 就是 5 
//	return 0;
//}


//int main()
//{
//	char* a[] = { "work","at","alibaba" };
//	char** pa = a;
//	pa++;
//	printf("%s\n", *pa);
//	return 0;
//}

//#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };//
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}
